{{>licenseInfo}}
package {{package}};

import java.util.Objects;
import {{invokerPackage}}.ApiResponse;

{{#jsonb}}
import jakarta.json.bind.JsonbBuilder;
{{/jsonb}}
{{#jackson}}
import com.fasterxml.jackson.databind.ObjectMapper;
{{/jackson}}

import io.helidon.common.GenericType;
import io.helidon.common.media.type.MediaType;
import io.helidon.config.Config;
import io.helidon.http.media.MediaSupport;
{{#jsonb}}import io.helidon.http.media.jsonb.JsonbSupport;{{/jsonb}}
{{#jackson}}import io.helidon.http.media.jackson.JacksonSupport;{{/jackson}}
import io.helidon.webclient.api.HttpClientRequest;
import io.helidon.webclient.api.HttpClientResponse;
{{#hasHeaderParams}}
import io.helidon.http.ClientRequestHeaders;
import io.helidon.http.HeaderNames;
{{/hasHeaderParams}}

import {{invokerPackage}}.ApiClient;

{{#x-helidon-implImports}}import {{import}};
{{/x-helidon-implImports}}

{{#appName}}
/**
 * {{{appName}}}
 *
 {{#appDescription}}
 * <p>{{{.}}}
 {{/appDescription}}
 */
{{/appName}}
public class {{classname}}Impl implements {{classname}} {

  private final ApiClient apiClient;

{{#operations}}
    {{#operation}}
  protected static final GenericType<{{>operationResponseTypeDecl}}> RESPONSE_TYPE_{{operationId}} = ResponseType.create({{#isArray}}List.class, {{/isArray}}{{#isMap}}Map.class, String.class, {{/isMap}}{{#returnBaseType}}{{returnBaseType}}{{/returnBaseType}}{{^returnBaseType}}Void{{/returnBaseType}}.class);
    {{/operation}}
{{/operations}}

  /**
   * Creates a new instance of {{classname}}Impl initialized with the specified {@link ApiClient}.
   *
   */
  public static {{classname}}Impl create(ApiClient apiClient) {
    return new {{classname}}Impl(apiClient);
  }

  protected {{classname}}Impl(ApiClient apiClient) {
    this.apiClient = apiClient;
  }

{{#operations}}
{{#operation}}
  {{#isDeprecated}}
  @Deprecated
  {{/isDeprecated}}
  @Override
  public {{>operationResponseSig}} {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) {
    {{#requiredParams}}
    Objects.requireNonNull({{paramName}}, "Required parameter '{{paramName}}' not specified");
    {{/requiredParams}}
    HttpClientRequest clientRequest = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
    return {{operationId}}Submit(clientRequest{{#allParams}}, {{paramName}}{{/allParams}});
  }

  /**
   * Creates a {@code WebClientRequestBuilder} for the {{operationId}} operation.
   * Optional customization point for subclasses.
   *
   {{#allParams}}
   * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}
   {{/allParams}}
   * @return HttpClientRequest for {{operationId}}
   */
  protected HttpClientRequest {{operationId}}HttpClientRequest({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) {
      HttpClientRequest clientRequest = apiClient.webClient()
            .method("{{httpMethod}}");

    {{#hasQueryParams}}
    List<Pair> queryParams = new ArrayList<>();
        {{#queryParams}}
            {{#collectionFormat}}
    queryParams.addAll(ApiClient.parameterToPairs("{{{collectionFormat}}}", "{{baseName}}", {{paramName}}));
            {{/collectionFormat}}
            {{^collectionFormat}}
                {{#isDeepObject}}
    if ({{paramName}} != null) {
                    {{#items.vars}}
      queryParams.addAll(ApiClient.parameterToPairs({{#isArray}}"csv", {{/isArray}}"{{baseName}}", {{paramName}}.{{getter}}()));
                    {{/items.vars}}
    }
                {{/isDeepObject}}
                {{^isDeepObject}}
                    {{#isExplode}}
                        {{#hasVars}}
                            {{#vars}}
    queryParams.addAll(ApiClent.parameterToPairs("{{baseName}}", {{paramName}}.{{getter}}()));
                            {{/vars}}
                        {{/hasVars}}
                        {{^hasVars}}
    queryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}}));
                        {{/hasVars}}
                    {{/isExplode}}
                    {{^isExplode}}
    queryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}}));
                    {{/isExplode}}
                {{/isDeepObject}}
            {{/collectionFormat}}
        {{/queryParams}}
    queryParams.forEach(p -> clientRequest.queryParam(p.getName(), p.getValue()));

    {{/hasQueryParams}}
    {{#hasHeaderParams}}
    ClientRequestHeaders headers = clientRequest.headers();
        {{#headerParams}}
    if ({{paramName}} != null) {
      headers.add(HeaderNames.create("{{baseName}}", {{paramName}}{{^isInteger}}{{^isString}}.toString(){{/isString}}{{/isInteger}});
    }
        {{/headerParams}}

    {{/hasHeaderParams}}
    {{#hasCookieParams}}
    String cookies = new StringJoiner("; ")
        {{#cookieParams}}
            .add("{{{baseName}}}=" + {{{paramName}}})
        {{/cookieParams}}
            .toString();
    clientRequest.headers().add(HeaderNames.COOKIE, cookies);

    {{/hasCookieParams}}
    clientRequest.path("{{{path}}}");
    {{#pathParams}}
    clientRequest.pathParam("{{{paramName}}}", {{paramName}});
    {{/pathParams}}
    {/hasPathParams}}
    {{#bodyParam}}
    clientRequest.contentType(MediaType.APPLICATION_JSON);
    {{/bodyParam}}
    {{#hasFormParams}}
    clientRequest.contentType(MediaType.APPLICATION_FORM_URLENCODED);
    {{/hasFormParams}}
    clientRequest.accept(MediaType.APPLICATION_JSON);

    return clientRequest;
  }

  /**
   * Initiates the request for the {{operationId}} operation.
   * Optional customization point for subclasses.
   *
   * @param clientRequest the request builder to use for submitting the request
   {{#allParams}}
   * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}
   {{/allParams}}
   * @return {@code {{>operationResponseSig}}} for the submitted request
   */
  protected {{>operationResponseSig}} {{operationId}}Submit(WebClientRequestBuilder clientRequest{{#allParams}}, {{{dataType}}} {{paramName}}{{/allParams}}) {
    {{#hasFormParams}}
    String formParams = new StringJoiner("&")
        {{#formParams}}
            .add("{{{baseName}}}=" + {{paramName}})
        {{/formParams}}
            .toString();
    {{/hasFormParams}}
    HttpClientResponse clientResponse = clientRequest.submit({{#bodyParam}}{{paramName}}{{/bodyParam}}{{#hasFormParams}}formParams{{/hasFormParams}});
    // Single<WebClientResponse> webClientResponse = clientRequest.submit({{#bodyParam}}{{paramName}}{{/bodyParam}}{{#hasFormParams}}formParams{{/hasFormParams}});
    return ApiResponse.create(RESPONSE_TYPE_{{operationId}}, clientResponse);
  }

{{/operation}}
{{/operations}}
}
